package com.atguigu.gmall.product.mapper;

import com.atguigu.gmall.model.product.SkuInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

/**
 * projectName: gmall
 *
 * @author: 陈鹏
 * time: 2022/9/23 16:11 星期五
 * description: sku_info表的映射
 */
@Mapper
public interface SkuInfoMapper extends BaseMapper<SkuInfo> {

    /**
     * 上架或者下架
     * @param skuId
     * @param status
     * @return
     */
    @Update("update sku_info set is_sale = #{status} where id = #{skuId}")
    public int upOrDown(@Param("skuId") Long skuId, @Param("status") short status);

    /**
     * 扣减库存
     * @param skuId
     * @param num
     * @return
     */
    @Update("update sku_info set stock = stock - #{num} where id = #{skuId} and stock >= #{num}")
    public int decount(@Param("skuId") Long skuId,
                       @Param("num") Integer num);

    /**
     * 回滚库存
     * @param skuId
     * @param num
     * @return
     */
    @Update("update sku_info set stock = stock + #{num} where id = #{skuId}")
    public int rollback(@Param("skuId") Long skuId,
                        @Param("num") Integer num);


    /**
     * mysql线程安全
     * 隔离级别:
     *  读未提交: AB两个事务操作数据的时候,A事务可以读取到B事务未提交的操作--->问题: 脏读 幻读 不可重复读
     *  读已提交: AB两个事务操作数据的时候,A事务只能读取到B提交的数据--->问题: 幻读 不可重复读
     *  可重复读(默认隔离级别): 同一个事务内多次读取同一份数据得到的结果是一样--->问题: 幻读
     *  串行化: 抢一个个来--->单线程操作数据库--->没有问题
     * 问题三种:
     *  脏读: A事务操作数据未提交,B事务读取到A事务操作的内容,A事务提交失败!
     *  幻读:       同一个事务内,同一个查询多次查询到的结果不一样(新增)
     *  不可重复读: 同一个事务内,对同一份数据多次查询到的结果不一样(修改)
     *
     *  默认存储引擎: innoDB
     *  支持行锁---->前提是数据存在!
     *      1.可以控制修改
     *      2.无法控制新增
     */

    /**
     * 乐观锁: 乐观的认为自己需要修改的数据没有其他人操作
     *  在数据表中设计一个version(版本),同时给与初始值1
     *      A同学,查询的操作(version=1), update sku_info set stock=99,version=verions+1 where id = 1 and version = 1;
     *      B同学, 查询的操作(version=1), update sku_info set stock=99,version=verions+1 where id = 1 and version = 1;
     *  A同学或B同学修改成功,version=2,另外一个同学会失败!
     * 悲观锁: 悲观认为自己需要修改的数据可能被其他人修改
     *  排他锁
     *  实现方案:
     *      1.开启事务
     *      2.select * from sku_info where id = 1 for update;(加锁)
     *      3.执行自己的修改操作
     *      4.提交事务(释放锁)
     * 问题:
     * 1.容易产生死锁
     */
}
